home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Compression / Opener / Source / utils / xlharc / lharc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-15  |  48.6 KB  |  2,190 lines

  1. /*----------------------------------------------------------------------*/
  2. /*        LHarc Archiver Driver for UNIX                */
  3. /*                                    */
  4. /*        Copyright(C) MCMLXXXIX  Yooichi.Tagawa            */
  5. /*        Thanks to H.Yoshizaki. (MS-DOS LHarc)            */
  6. /*                                    */
  7. /*  V0.00  Original                1988.05.23  Y.Tagawa    */
  8. /*  V0.01  Alpha Version (for 4.2BSD)        1989.05.28  Y.Tagawa    */
  9. /*  V0.02  Alpha Version Rel.2            1989.05.29  Y.Tagawa    */
  10. /*  V0.03  Release #3  Beta Version        1989.07.02  Y.Tagawa    */
  11. /*  V0.03a Fix few bug                          1989.07.03  Y.Tagawa    */
  12. /*  V0.04  A lot of bugs fixed, strict mode     1990.01.13  Kai Uwe Rommel */
  13. /*  V1.00  f and t commands, v option added     1990.01.27  Kai Uwe Rommel */
  14. /*----------------------------------------------------------------------*/
  15.  
  16.  
  17. #include <stdio.h>
  18. #include <ctype.h>
  19. #include <signal.h>
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22.  
  23. #ifdef PROF
  24. #include <profile.h>
  25. #endif
  26.  
  27. #define STRICT
  28. #define FASTCOPY
  29.  
  30. #ifdef MSDOS
  31. #include <fcntl.h>
  32. extern unsigned char _osmode;
  33. extern FILE *popen();
  34. extern pclose();
  35. #define ftruncate chsize
  36. #define mktemp Mktemp
  37. #define SYSTIME_HAS_NO_TM
  38. #define NOBSTRING
  39. #define SYSNAME (_osmode ? "OS/2" : "MS-DOS")
  40. #define OUR_EXTEND (_osmode ? EXTEND_OS2 : EXTEND_MSDOS)
  41. #define FILENAME_LENGTH 128
  42. #define NULLFILE "nul"
  43. #define TMP_FILENAME_TEMPLATE "lhXXXXXX"
  44. #define NOT_COMPATIBLE_MODE
  45. #define RMODE "rb"
  46. #define WMODE "wb"
  47. #else
  48. #include <sys/file.h>
  49. #include <sys/time.h>
  50. #define SYSNAME "UNIX"
  51. #define OUR_EXTEND EXTEND_UNIX
  52. #define FILENAME_LENGTH    1024
  53. #define NULLFILE "/dev/null"
  54. #define RMODE "r"
  55. #define WMODE "w"
  56. #endif
  57.  
  58. #ifdef SYSTIME_HAS_NO_TM
  59. /* most of System V,  define SYSTIME_HAS_NO_TM */
  60. #include <time.h>
  61. #endif
  62.  
  63. /* #include <strings.h> */
  64. #include <string.h>
  65.  
  66.  
  67. /*----------------------------------------------------------------------*/
  68. /*            DIRECTORY ACCESS STUFF                */
  69. /*----------------------------------------------------------------------*/
  70. #ifndef NODIRECTORY
  71. #ifdef SYSV_SYSTEM_DIR
  72.  
  73. #include <dirent.h>
  74. #define DIRENTRY    struct dirent
  75. #define NAMREN(p)    strlen (p->d_name)
  76.  
  77. #else    /* not SYSV_SYSTEM_DIR */
  78.  
  79. #ifdef NONSYSTEM_DIR_LIBRARY
  80. #include "lhdir.h"
  81. #else    /* not NONSYSTEM_DIR_LIBRARY */
  82. #include <sys/dir.h>
  83. #endif    /* not NONSYSTEM_DIR_LIBRARY */
  84.  
  85. #define DIRENTRY    struct direct
  86. #define NAMLEN(p)    p->d_namlen
  87.  
  88. extern DIR *opendir ();
  89. extern struct direct *readdir ();
  90.  
  91. #endif    /* not SYSV_SYSTEM_DIR */
  92. #endif
  93.  
  94. /*----------------------------------------------------------------------*/
  95. /*            FILE ATTRIBUTES                    */
  96. /*----------------------------------------------------------------------*/
  97.  
  98. /* If file mode is not compatible between your Machine/OS and
  99.    LHarc standard UNIX file mode.
  100.    (See UNIX Manual stat(1), <sys/stat.h>,
  101.    and/or below UNIX_* difinitions. ) */
  102. /* #define NOT_COMPATIBLE_MODE */
  103.  
  104.  
  105. /*----------------------------------------------------------------------*/
  106. /*            MEMORY FUNCTIONS                 */
  107. /*----------------------------------------------------------------------*/
  108.  
  109. #ifdef NOBSTRING
  110. #ifdef __ANSI__
  111. #include "mem.h"
  112. #define bcmp(a,b,n) memcmp ((a),(b),(n))
  113. #define bcopy(s,d,n) memmove((d),(s),(n))
  114. #define bzero(d,n) memset((d),0,(n))
  115. #else    /* not __ANSI__ */
  116. #include "memory.h"
  117. #define bcmp(a,b,n) memcmp ((a),(b),(n))
  118. #define bcopy(s,d,n) memcpy ((d),(s),(n))    /* movmem((s),(d),(n)) */
  119. #define bzero(d,n) memset((d),0,(n))
  120. #endif    /* not __ANSI__ */
  121. #endif    /* NOBSTRING */
  122.  
  123.  
  124. /*----------------------------------------------------------------------*/
  125. /*            YOUR CUSTOMIZIES                */
  126. /*----------------------------------------------------------------------*/
  127. /* These difinitions are changable to you like. */
  128. /* #define ARCHIVENAME_EXTENTION    ".LZH"        */
  129. /* #define TMP_FILENAME_TEMPLATE    "/tmp/lhXXXXXX"    */
  130. /* #define BACKUPNAME_EXTENTION        ".BAK"        */
  131. /* #define MULTIBYTE_CHAR                */
  132.  
  133.  
  134.  
  135. #define SJC_FIRST_P(c)            \
  136.   (((unsigned char)(c) >= 0x80) &&    \
  137.    (((unsigned char)(c) < 0xa0) ||    \
  138.     ((unsigned char)(c) >= 0xe0) &&    \
  139.     ((unsigned char)(c) < 0xfd)))
  140. #define SJC_SECOND_P(c)            \
  141.   (((unsigned char)(c) >= 0x40) &&    \
  142.    ((unsigned char)(c) < 0xfd) &&    \
  143.    ((ungigned char)(c) != 0x7f))
  144.  
  145. #ifdef MULTIBYTE_CHAR
  146. #define MULTIBYTE_FIRST_P    SJC_FIRST_P
  147. #define MULTIBYTE_SECOND_P    SJC_SECOND_P
  148. #endif
  149.  
  150. /*----------------------------------------------------------------------*/
  151. /*            OTHER DIFINITIONS                */
  152. /*----------------------------------------------------------------------*/
  153.  
  154. #ifndef SEEK_SET
  155. #define SEEK_SET    0
  156. #define SEEK_CUR    1
  157. #define SEEK_END    2
  158. #endif
  159.  
  160.  
  161. /* non-integral functions */
  162. extern struct tm *localtime ();
  163. extern char *getenv ();
  164. extern char *malloc ();
  165. extern char *realloc ();
  166.  
  167. extern int rson[];
  168.  
  169. /* external variables */
  170. extern int errno;
  171.  
  172.  
  173. #define    FALSE    0
  174. #define TRUE    1
  175. typedef int boolean;
  176.  
  177.  
  178. /*----------------------------------------------------------------------*/
  179. /*        LHarc FILE DIFINITIONS                    */
  180. /*----------------------------------------------------------------------*/
  181. #define METHOD_TYPE_STRAGE    5
  182. #define LZHUFF0_METHOD        "-lh0-"
  183. #define LZHUFF1_METHOD        "-lh1-"
  184. #define LARC4_METHOD        "-lz4-"
  185. #define LARC5_METHOD        "-lz5-"
  186.  
  187. #define I_HEADER_SIZE            0
  188. #define I_HEADER_CHECKSUM        1
  189. #define I_METHOD            2
  190. #define I_PACKED_SIZE            7
  191. #define I_ORIGINAL_SIZE            11
  192. #define I_LAST_MODIFIED_STAMP        15
  193. #define I_ATTRIBUTE            19
  194. #define I_NAME_LENGTH            21
  195. #define I_NAME                22
  196.  
  197. #define I_CRC                22 /* + name_length */
  198. #define I_EXTEND_TYPE            24 /* + name_length */
  199. #define I_MINOR_VERSION            25 /* + name_length */
  200. #define I_UNIX_LAST_MODIFIED_STAMP    26 /* + name_length */
  201. #define I_UNIX_MODE            30 /* + name_length */
  202. #define I_UNIX_UID            32 /* + name_length */
  203. #define I_UNIX_GID            34 /* + name_length */
  204. #define I_UNIX_EXTEND_BOTTOM        36 /* + name_length */
  205.  
  206.  
  207.  
  208. #define EXTEND_GENERIC  0
  209. #define EXTEND_UNIX    'U'
  210. #define EXTEND_MSDOS    'M'
  211. #define EXTEND_MACOS    'm'
  212. #define EXTEND_OS9    '9'
  213. #define EXTEND_OS2    '2'
  214. #define EXTEND_OS68K    'K'
  215. #define EXTEND_OS386    '3'
  216. #define EXTEND_HUMAN    'H'
  217. #define EXTEND_CPM    'C'
  218. #define EXTEND_FLEX    'F'
  219.  
  220. #define GENERIC_ATTRIBUTE        0x20
  221. #define GENERIC_DIRECTORY_ATTRIBUTE    0x10
  222.  
  223. #define CURRENT_UNIX_MINOR_VERSION    0x00
  224.  
  225.  
  226.  
  227. typedef struct LzHeader {
  228.   unsigned char        header_size;
  229.   char            method[METHOD_TYPE_STRAGE];
  230.   long            packed_size;
  231.   long            original_size;
  232.   long            last_modified_stamp;
  233.   unsigned short    attribute;
  234.   char            name[256];
  235.   unsigned short    crc;
  236.   boolean        has_crc;
  237.   unsigned char        extend_type;
  238.   unsigned char        minor_version;
  239.   /*  extend_type == EXTEND_UNIX  and convert from other type. */
  240.   time_t        unix_last_modified_stamp;
  241.   unsigned short    unix_mode;
  242.   unsigned short    unix_uid;
  243.   unsigned short    unix_gid;
  244. } LzHeader;
  245.  
  246. #define UNIX_FILE_TYPEMASK    0170000
  247. #define UNIX_FILE_REGULAR    0100000
  248. #define UNIX_FILE_DIRECTORY    0040000
  249. #define UNIX_SETUID        0004000
  250. #define UNIX_SETGID        0002000
  251. #define UNIX_STYCKYBIT        0001000
  252. #define UNIX_OWNER_READ_PERM    0000400
  253. #define UNIX_OWNER_WRITE_PERM    0000200
  254. #define UNIX_OWNER_EXEC_PERM    0000100
  255. #define UNIX_GROUP_READ_PERM    0000040
  256. #define UNIX_GROUP_WRITE_PERM    0000020
  257. #define UNIX_GROUP_EXEC_PERM    0000010
  258. #define UNIX_OTHER_READ_PERM    0000004
  259. #define UNIX_OTHER_WRITE_PERM    0000002
  260. #define UNIX_OTHER_EXEC_PERM    0000001
  261. #define UNIX_RW_RW_RW        0000666
  262.  
  263. #define LZHEADER_STRAGE        256
  264.  
  265. /*----------------------------------------------------------------------*/
  266. /*        PROGRAM                         */
  267. /*----------------------------------------------------------------------*/
  268.  
  269.  
  270. #define CMD_UNKNOWN    0
  271. #define CMD_EXTRACT    1
  272. #define CMD_APPEND    2
  273. #define CMD_VIEW    3
  274.  
  275. int      cmd = CMD_UNKNOWN;
  276. char     **cmd_filev;
  277. int      cmd_filec;
  278. char     *archive_name;
  279.  
  280. char     expanded_archive_name[FILENAME_LENGTH];
  281. char     temporary_name[FILENAME_LENGTH];
  282. char     pager[FILENAME_LENGTH];
  283.  
  284.  
  285. /* options */
  286. boolean    quiet = FALSE;
  287. boolean    text_mode = FALSE;
  288. /*boolean  verbose = FALSE; */
  289. boolean  noexec = FALSE; /* debugging option */
  290. boolean  force = FALSE;
  291. boolean  prof = FALSE;
  292.  
  293.  
  294. /* view flags */
  295. boolean  long_format_listing = FALSE;
  296.  
  297. /* extract flags */
  298. boolean  output_to_test = FALSE;
  299. boolean  output_to_stdout = FALSE;
  300.  
  301. /* append flags */
  302. boolean  new_archive = FALSE;
  303. boolean  update_if_newer = FALSE;
  304. boolean  update_freshen = FALSE;
  305. boolean  delete_after_append = FALSE;
  306. boolean  delete_from_archive = FALSE;
  307.  
  308. boolean  remove_temporary_at_error = FALSE;
  309.  
  310.  
  311. /*----------------------------------------------------------------------*/
  312. /* NOTES :    Text File Format                    */
  313. /*    GENERATOR        NewLine                    */
  314. /*    [generic]        0D 0A                    */
  315. /*    [MS-DOS]        0D 0A                    */
  316. /*    [MacOS]            0D                    */
  317. /*    [UNIX]            0A                    */
  318. /*----------------------------------------------------------------------*/
  319.  
  320. char *myname;
  321.  
  322.  
  323. void userbreak(void)
  324. {
  325.     error("Interrupt.");
  326. }
  327.  
  328.  
  329. main (argc, argv)
  330.      int argc;
  331.      char *argv[];
  332. {
  333.   char *p;
  334.  
  335.   myname = argv[0];
  336.   signal(SIGINT, userbreak);
  337.  
  338. #ifdef PROF
  339.   PROFINIT(PT_USER|PT_USEKP, NULL);
  340.   PROFCLEAR(PT_USER);
  341.   PROFON(PT_USER);
  342. #endif
  343.  
  344.   if (argc < 3)
  345.     print_tiny_usage_and_exit ();
  346.  
  347.   /* commands */
  348. #ifdef MSDOS
  349.   switch (tolower(argv[1][0]))
  350. #else
  351.   switch (argv[1][0])
  352. #endif
  353.     {
  354.     case 'x':
  355.     case 'e':
  356.       cmd = CMD_EXTRACT;
  357.       break;
  358.  
  359.     case 't':
  360.       output_to_test = TRUE;
  361.       cmd = CMD_EXTRACT;
  362.       break;
  363.  
  364.     case 'p':
  365.       output_to_stdout = TRUE;
  366.       cmd = CMD_EXTRACT;
  367.       break;
  368.  
  369.     case 'c':
  370.       new_archive = TRUE;
  371.       cmd = CMD_APPEND;
  372.       break;
  373.  
  374.     case 'a':
  375.       cmd = CMD_APPEND;
  376.       break;
  377.  
  378.     case 'd':
  379.       delete_from_archive = TRUE;
  380.       cmd = CMD_APPEND;
  381.       break;
  382.  
  383.     case 'u':
  384.       update_if_newer = TRUE;
  385.       cmd = CMD_APPEND;
  386.       break;
  387.  
  388.     case 'f':
  389.       update_if_newer = update_freshen = TRUE;
  390.       cmd = CMD_APPEND;
  391.       break;
  392.  
  393.     case 'm':
  394.       delete_after_append = TRUE;
  395.       cmd = CMD_APPEND;
  396.       break;
  397.  
  398.     case 'v':
  399.       cmd = CMD_VIEW;
  400.       break;
  401.  
  402.     case 'l':
  403.       long_format_listing = TRUE;
  404.       cmd = CMD_VIEW;
  405.       break;
  406.  
  407.     case 'h':
  408.     default:
  409.       print_tiny_usage_and_exit ();
  410.     }
  411.  
  412.   /* options */
  413.   p = &argv[1][1];
  414.   for (p = &argv[1][1]; *p; p++)
  415.     {
  416. #ifdef MSDOS
  417.       switch (tolower(*p))
  418. #else
  419.       switch (*p)
  420. #endif
  421.     {
  422.     case 'q':    quiet = TRUE; break;
  423.     case 'f':    force = TRUE; break;
  424. /*      case 'p':       prof = TRUE; break; */
  425. /*      case 'v':       verbose = TRUE; break; */
  426.         case 'v':       strcpy(pager, p + 1); *(p + 1) = 0; break;
  427.     case 't':    text_mode = TRUE; break;
  428.     case 'n':    noexec = TRUE; break;
  429.  
  430.     default:
  431.           fprintf (stderr, "unknown option '%c'.\n", *p);
  432.       exit (1);
  433.         }
  434.     }
  435.  
  436.   /* archive file name */
  437.   archive_name = argv[2];
  438.  
  439.   /* target file name */
  440.   cmd_filec = argc - 3;
  441.   cmd_filev = argv + 3;
  442.   sort_files ();
  443.  
  444.   switch (cmd)
  445.     {
  446.     case CMD_EXTRACT:    cmd_extract ();    break;
  447.     case CMD_APPEND:    cmd_append ();    break;
  448.     case CMD_VIEW:    cmd_view ();    break;
  449.     }
  450.  
  451. #ifdef PROF
  452.   PROFOFF(PT_USER);
  453.   PROFDUMP(PT_USER, "profile.out");
  454.   PROFFREE(PT_USER);
  455. #endif
  456.  
  457.   exit (0);
  458. }
  459.  
  460. print_tiny_usage_and_exit ()
  461. {
  462.   printf("\nC-LHarc for %s Version 1.00   (C) 1989-1990 Y.Tagawa, Kai Uwe Rommel\n"
  463.          "\nUsage: %s {axevlufdmctp}[qnftv] archive_file [files or directories...]\n",
  464.          SYSNAME, myname);
  465.   printf("\nCommands:                    Options:\n"
  466.          "  a   Append                   q   quiet\n"
  467.          "  x,e EXtract                  n   no execute\n"
  468.          "  v,l View/List                f   force (over write at extract)\n"
  469.          "  u   Update                   t   files are TEXT files\n"
  470.          "  f   Freshen                  v<pager>  use file pager for p command\n"
  471.          "  d   Delete\n"
  472.          "  m   Move\n"
  473.          "  c   re-Construct new archive\n"
  474.          "  t   Test archive\n"
  475.          "  p   Print to STDOUT\n");
  476.   exit (1);
  477. }
  478.  
  479. message (title, msg)
  480.      char *title, *msg;
  481. {
  482.   fprintf (stderr, "%s ", myname);
  483.   if (errno == 0)
  484.     fprintf (stderr, "%s %s\n", title, msg);
  485.   else
  486.     perror (msg);
  487. }
  488.  
  489. warning (msg)
  490.      char *msg;
  491. {
  492.   message ("Warning:", msg);
  493. }
  494.  
  495. error (msg)
  496.      char *msg;
  497. {
  498.   message ("Error:", msg);
  499.  
  500.   if (remove_temporary_at_error)
  501.   {
  502. #ifdef MSDOS
  503.     fcloseall();
  504. #endif
  505.     unlink (temporary_name);
  506.   }
  507.  
  508.   exit (1);
  509. }
  510.  
  511. char *writting_filename;
  512. char *reading_filename;
  513.  
  514. write_error ()
  515. {
  516.   error (writting_filename);
  517. }
  518.  
  519. read_error ()
  520. {
  521.   error (reading_filename);
  522. }
  523.  
  524.  
  525.  
  526. /*----------------------------------------------------------------------*/
  527. /*                                    */
  528. /*----------------------------------------------------------------------*/
  529.  
  530. boolean expand_archive_name (dst, src)
  531.      char *dst, *src;
  532. {
  533.   register char *p, *dot;
  534.  
  535.   strcpy (dst, src);
  536.  
  537.   for (p = dst, dot = (char*)0; *p; p++)
  538.     if (*p == '.')
  539.       dot = p;
  540.     else if (*p == '/' || *p == '\\')
  541.       dot = (char*)0;
  542.  
  543.   if (dot)
  544.     p = dot;
  545.  
  546. #ifdef ARCHIVENAME_EXTENTION
  547.   strcpy (p, ARCHIVENAME_EXTENTION);
  548. #else
  549.   strcpy (p, ".lzh");
  550. #endif
  551.   return (strcmp (dst, src) != 0);
  552. }
  553.  
  554. #ifdef MSDOS
  555. #define STRING_COMPARE(a,b) stricmp((a),(b))
  556. #else
  557. #define STRING_COMPARE(a,b) strcmp((a),(b))
  558. #endif
  559.  
  560. int sort_by_ascii (a, b)
  561.      char **a, **b;
  562. {
  563.   return STRING_COMPARE (*a, *b);
  564. }
  565.  
  566. sort_files ()
  567. {
  568.   qsort (cmd_filev, cmd_filec, sizeof (char*), sort_by_ascii);
  569. }
  570.  
  571. #ifndef MSDOS
  572. char *strdup (string)
  573.      char *string;
  574. {
  575.   int    len = strlen (string) + 1;
  576.   char    *p = malloc (len);
  577.   bcopy (string, p, len);
  578.   return p;
  579. }
  580. #endif
  581.  
  582. #ifdef NODIRECTORY
  583. /* please need your imprementation */
  584. boolean find_files (name, v_filec, v_filev)
  585.      char    *name;
  586.      int    *v_filec;
  587.      char    ***v_filev;
  588. {
  589.   return FALSE;            /* DUMMY */
  590. }
  591. #else
  592. boolean find_files (name, v_filec, v_filev)
  593.      char    *name;
  594.      int    *v_filec;
  595.      char    ***v_filev;
  596. {
  597.   char        newname[FILENAME_LENGTH];
  598.   int         len, n;
  599.   DIR        *dirp;
  600.   DIRENTRY    *dp;
  601.   int           alloc_size = 64; /* any (^_^) */
  602.   char        **filev;
  603.   int        filec = 0;
  604.  
  605.   if ( strcmp(name, ".") == 0 )
  606.     newname[0] = 0;
  607.   else
  608.     strcpy (newname, name);
  609.  
  610.   len = strlen (newname);
  611.   dirp = opendir (name);
  612.  
  613.   if (dirp)
  614.     {
  615.       filev = (char**)malloc (alloc_size * sizeof(char *));
  616.       if (!filev)
  617.     error ("not enough memory");
  618.  
  619.       for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
  620.     {
  621.       n = NAMLEN (dp);
  622.           if (
  623. #ifndef MSDOS
  624.               (dp->d_ino != 0) &&
  625. #endif
  626.               ((dp->d_name[0] != '.') ||
  627.                  ((n != 1) &&
  628.                  ((dp->d_name[1] != '.') ||
  629.          (n != 2)))) &&            /* exclude '.' and '..' */
  630.           (strcmp (dp->d_name, temporary_name) != 0) &&
  631.           (strcmp (dp->d_name, archive_name) != 0))
  632.         {
  633.               if ((len != 0) && (newname[len-1] != '/') && (newname[len-1] != '\\'))
  634.                 {
  635. #ifdef MSDOS
  636.                   newname[len] = '\\';
  637. #else
  638.                   newname[len] = '/';
  639. #endif
  640.           strncpy (newname+len+1, dp->d_name, n);
  641.           newname[len+n+1] = '\0';
  642.         }
  643.           else
  644.         {
  645.           strncpy (newname+len, dp->d_name, n);
  646.           newname[len+n] = '\0';
  647.         }
  648.  
  649.           filev[filec++] = strdup (newname);
  650.           if (filec == alloc_size)
  651.         {
  652.                   alloc_size += 64;
  653.                   filev = (char**)realloc (filev, alloc_size * sizeof(char *));
  654.         }
  655.         }
  656.     }
  657.       closedir (dirp);
  658.     }
  659.  
  660.   *v_filev = filev;
  661.   *v_filec = filec;
  662.   if (dirp)
  663.     {
  664.       qsort (filev, filec, sizeof (char*), sort_by_ascii);
  665.       return TRUE;
  666.     }
  667.   else
  668.     return FALSE;
  669. }
  670. #endif
  671.  
  672. free_files (filec, filev)
  673.      int    filec;
  674.      char    **filev;
  675. {
  676.   int        i;
  677.  
  678.   for (i = 0; i < filec; i ++)
  679.     free (filev[i]);
  680.  
  681.   free (filev);
  682. }
  683.  
  684.  
  685. /*----------------------------------------------------------------------*/
  686. /*                                    */
  687. /*----------------------------------------------------------------------*/
  688.  
  689. int calc_sum (p, len)
  690.      register char *p;
  691.      register int len;
  692. {
  693.   register int sum;
  694.  
  695.   for (sum = 0; len; len--)
  696.     sum += *p++;
  697.  
  698.   return sum & 0xff;
  699. }
  700.  
  701. unsigned char *get_ptr;
  702. #define setup_get(PTR) get_ptr = (unsigned char*)(PTR)
  703. #define get_byte() (*get_ptr++)
  704. #define put_ptr    get_ptr
  705. #define setup_put(PTR) put_ptr = (unsigned char*)(PTR)
  706. #define put_byte(c) *put_ptr++ = (unsigned char)(c)
  707.  
  708. unsigned short get_word ()
  709. {
  710.   int b0, b1;
  711.  
  712.   b0 = get_byte ();
  713.   b1 = get_byte ();
  714.   return (b1 << 8) + b0;
  715. }
  716.  
  717. put_word (v)
  718.      unsigned int    v;
  719. {
  720.   put_byte (v);
  721.   put_byte (v >> 8);
  722. }
  723.  
  724. long get_longword ()
  725. {
  726.   long b0, b1, b2, b3;
  727.  
  728.   b0 = get_byte ();
  729.   b1 = get_byte ();
  730.   b2 = get_byte ();
  731.   b3 = get_byte ();
  732.   return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
  733. }
  734.  
  735. put_longword (v)
  736.      long v;
  737. {
  738.   put_byte (v);
  739.   put_byte (v >> 8);
  740.   put_byte (v >> 16);
  741.   put_byte (v >> 24);
  742. }
  743.  
  744.  
  745. msdos_to_unix_filename (name, len)
  746.      register char *name;
  747.      register int len;
  748. {
  749.   register int i;
  750.  
  751. #ifdef MULTIBYTE_CHAR
  752.   for (i = 0; i < len; i ++)
  753.     {
  754.       if (MULTIBYTE_FIRST_P (name[i]) &&
  755.       MULTIBYTE_SECOND_P (name[i+1]))
  756.         i ++;
  757. #ifndef MSDOS
  758.       else if (name[i] == '\\')
  759.         name[i] = '/';
  760. #endif
  761.       else if (isupper (name[i]))
  762.     name[i] = tolower (name[i]);
  763.     }
  764. #else
  765.   for (i = 0; i < len; i ++)
  766.     {
  767. #ifndef MSDOS
  768.       if (name[i] == '\\')
  769.     name[i] = '/';
  770.       else
  771. #endif
  772.         if (isupper (name[i]))
  773.           name[i] = tolower (name[i]);
  774.     }
  775. #endif
  776. }
  777.  
  778. generic_to_unix_filename (name, len)
  779.      register char *name;
  780.      register int len;
  781. {
  782.   register int i;
  783.   boolean    lower_case_used = FALSE;
  784.  
  785. #ifdef MULTIBYTE_CHAR
  786.   for (i = 0; i < len; i ++)
  787.     {
  788.       if (MULTIBYTE_FIRST_P (name[i]) &&
  789.       MULTIBYTE_SECOND_P (name[i+1]))
  790.     i ++;
  791.       else if (islower (name[i]))
  792.     {
  793.       lower_case_used = TRUE;
  794.       break;
  795.     }
  796.     }
  797.   for (i = 0; i < len; i ++)
  798.     {
  799.       if (MULTIBYTE_FIRST_P (name[i]) &&
  800.       MULTIBYTE_SECOND_P (name[i+1]))
  801.         i ++;
  802. #ifndef MSDOS
  803.       else if (name[i] == '\\')
  804.         name[i] = '/';
  805. #endif
  806.       else if (!lower_case_used && isupper (name[i]))
  807.     name[i] = tolower (name[i]);
  808.     }
  809. #else
  810.   for (i = 0; i < len; i ++)
  811.     if (islower (name[i]))
  812.       {
  813.     lower_case_used = TRUE;
  814.     break;
  815.       }
  816.   for (i = 0; i < len; i ++)
  817.     {
  818. #ifndef MSDOS
  819.       if (name[i] == '\\')
  820.     name[i] = '/';
  821.       else
  822. #endif
  823.         if (!lower_case_used && isupper (name[i]))
  824.           name[i] = tolower (name[i]);
  825.     }
  826. #endif
  827. }
  828.  
  829. macos_to_unix_filename (name, len)
  830.      register char *name;
  831.      register int len;
  832. {
  833.   register int i;
  834.  
  835.   for (i = 0; i < len; i ++)
  836.     {
  837.       if (name[i] == ':')
  838.     name[i] = '/';
  839.       else if (name[i] == '/')
  840.     name[i] = ':';
  841.     }
  842. }
  843.  
  844. /*----------------------------------------------------------------------*/
  845. /*                                    */
  846. /*    Generic stamp format:                        */
  847. /*                                    */
  848. /*     31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16        */
  849. /*    |<-------- year ------->|<- month ->|<-- day -->|        */
  850. /*                                    */
  851. /*     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0        */
  852. /*    |<--- hour --->|<---- minute --->|<- second*2 ->|        */
  853. /*                                    */
  854. /*----------------------------------------------------------------------*/
  855.  
  856.  
  857. long gettz ()
  858. {
  859. #ifdef MSDOS
  860.    return timezone;
  861. #else
  862.    struct timeval    tp;
  863.    struct timezone    tzp;
  864.    gettimeofday (&tp, &tzp);    /* specific to 4.3BSD */
  865. /* return (tzp.tz_minuteswest * 60 + (tzp.tz_dsttime != 0 ? 60L * 60L : 0));*/
  866.    return (tzp.tz_minuteswest * 60);
  867. #endif
  868. }
  869.  
  870. #ifdef NOT_USED
  871. struct tm *msdos_to_unix_stamp_tm (a)
  872.      long a;
  873. {
  874.   static struct tm t;
  875.   t.tm_sec    = ( a          & 0x1f) * 2;
  876.   t.tm_min    =  (a >>    5) & 0x3f;
  877.   t.tm_hour    =  (a >>   11) & 0x1f;
  878.   t.tm_mday    =  (a >>   16) & 0x1f;
  879.   t.tm_mon    =  (a >> 16+5) & 0x0f - 1;
  880.   t.tm_year    = ((a >> 16+9) & 0x7f) + 80;
  881.   return &t;
  882. }
  883. #endif
  884.  
  885. time_t generic_to_unix_stamp (t)
  886.      long t;
  887. {
  888.   struct tm tm;
  889.   long longtime;
  890.   static unsigned int dsboy[12] =
  891.     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  892.   unsigned long days;
  893.  
  894.   tm.tm_year =  ((int)(t >> 25) & 0x7f) + 80;
  895.   tm.tm_mon  =  ((int)(t >> 21) & 0x0f) - 1;     /* 0..11 means Jan..Dec */
  896.   tm.tm_mday =  (int)(t >> 16) & 0x1f;         /* 1..31 means 1st,...31st */
  897.  
  898.   tm.tm_hour =  ((int)t >> 11) & 0x1f;
  899.   tm.tm_min  =  ((int)t >> 5)  & 0x3f;
  900.   tm.tm_sec  =  ((int)t        & 0x1f) * 2;
  901.  
  902. #ifdef MSDOS
  903.   longtime = mktime(&tm);
  904. #else
  905.                                       /* Calculate days since 1970.01.01 */
  906.   days = (365 * (tm.tm_year - 70) +   /* days due to whole years */
  907.           (tm.tm_year - 70 + 1) / 4 + /* days due to leap years */
  908.           dsboy[tm.tm_mon] +          /* days since beginning of this year */
  909.           tm.tm_mday-1);              /* days since beginning of month */
  910.  
  911.   if ((tm.tm_year % 4 == 0) &&
  912.       (tm.tm_year % 400 != 0) &&
  913.       (tm.tm_mon >= 2))         /* if this is a leap year and month */
  914.     days++;            /* is March or later, add a day */
  915.  
  916.   /* Knowing the days, we can find seconds */
  917.   longtime = (((days * 24) + tm.tm_hour) * 60 + tm.tm_min) * 60 + tm.tm_sec;
  918.   longtime += gettz ();      /* adjust for timezone */
  919. #endif
  920.  
  921.   /* special case:  if MSDOS format date and time were zero, then we set
  922.      time to be zero here too. */
  923.   if (t == 0)
  924.     longtime = 0;
  925.  
  926.   /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00.  */
  927.   return (time_t)longtime;
  928. }
  929.  
  930. long unix_to_generic_stamp (t)
  931.      time_t t;
  932. {
  933.   struct tm *tm = localtime (&t);
  934.   unsigned long stamp;
  935.  
  936.   stamp =  ( ((long)(tm->tm_year - 80)) << 25 );
  937.   stamp += ( ((long)(tm->tm_mon + 1))   << 21 );
  938.   stamp += ( ((long)(tm->tm_mday))      << 16 );
  939.   stamp += ( ((long)(tm->tm_hour))      << 11 );
  940.   stamp += ( ((long)(tm->tm_min))       << 5 );
  941.   stamp += ( ((long)(tm->tm_sec))       >> 1 );
  942.  
  943.   return stamp;
  944. }
  945.  
  946. /*----------------------------------------------------------------------*/
  947. /*                                    */
  948. /*----------------------------------------------------------------------*/
  949.  
  950. boolean get_header (fp, hdr)
  951.      FILE *fp;
  952.      register LzHeader *hdr;
  953. {
  954.   int        header_size;
  955.   int        name_length;
  956.   char        data[LZHEADER_STRAGE];
  957.   int        checksum;
  958.   int        i;
  959.  
  960.   bzero (hdr, sizeof (LzHeader));
  961.  
  962.   if (((header_size = getc (fp)) == EOF) || (header_size == 0))
  963.     {
  964.       return FALSE;        /* finish */
  965.     }
  966.  
  967.   if (fread (data + I_HEADER_CHECKSUM,
  968.           sizeof (char), header_size + 1, fp) < header_size + 1)
  969.     {
  970.       error ("Invalid header (LHarc file ?)\a");
  971.       return FALSE;        /* finish */
  972.     }
  973.  
  974.   setup_get (data + I_HEADER_CHECKSUM);
  975.   checksum = calc_sum (data + I_METHOD, header_size);
  976.   if (get_byte () != checksum)
  977.     warning ("Checksum error (LHarc file?)\a");
  978.  
  979.   hdr->header_size = header_size;
  980.   bcopy (data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  981. #ifdef OLD
  982.   if ((bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  983.       (bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  984.       (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  985.       (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) != 0))
  986.     {
  987.       warning ("Unknown method (LHarc file ?)");
  988.       return FALSE;        /* invalid method */
  989.     }
  990. #endif
  991.   setup_get (data + I_PACKED_SIZE);
  992.   hdr->packed_size    = get_longword ();
  993.   hdr->original_size    = get_longword ();
  994.   hdr->last_modified_stamp = get_longword ();
  995.   hdr->attribute    = get_word ();
  996.   name_length        = get_byte ();
  997.   for (i = 0; i < name_length; i ++)
  998.     hdr->name[i] =(char)get_byte ();
  999.   hdr->name[name_length] = '\0';
  1000.  
  1001.   /* defaults for other type */
  1002.   hdr->unix_mode    = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
  1003.   hdr->unix_gid     = 0;
  1004.   hdr->unix_uid        = 0;
  1005.  
  1006.   if (header_size - name_length >= 24)
  1007.     {                /* EXTEND FORMAT */
  1008.       hdr->crc                = get_word ();
  1009.       hdr->extend_type            = get_byte ();
  1010.       hdr->minor_version        = get_byte ();
  1011.       hdr->has_crc = TRUE;
  1012.     }
  1013.   else if (header_size - name_length == 22)
  1014.     {                /* Generic with CRC */
  1015.       hdr->crc                = get_word ();
  1016.       hdr->extend_type            = EXTEND_GENERIC;
  1017.       hdr->has_crc = TRUE;
  1018.     }
  1019.   else if (header_size - name_length == 20)
  1020.     {                /* Generic no CRC */
  1021.       hdr->extend_type            = EXTEND_GENERIC;
  1022.       hdr->has_crc = FALSE;
  1023.     }
  1024.   else
  1025.     {
  1026.       warning ("Unknown header (LHarc file ?)");
  1027.       return FALSE;
  1028.     }
  1029.  
  1030.   switch (hdr->extend_type)
  1031.     {
  1032.     case EXTEND_MSDOS:
  1033.       msdos_to_unix_filename (hdr->name, name_length);
  1034.       hdr->unix_last_modified_stamp    =
  1035.     generic_to_unix_stamp (hdr->last_modified_stamp);
  1036.       break;
  1037.  
  1038.     case EXTEND_UNIX:
  1039.       hdr->unix_last_modified_stamp    = (time_t)get_longword ();
  1040.       hdr->unix_mode            = get_word ();
  1041.       hdr->unix_uid            = get_word ();
  1042.       hdr->unix_gid            = get_word ();
  1043.       break;
  1044.  
  1045.     case EXTEND_MACOS:
  1046.       macos_to_unix_filename (hdr->name, name_length);
  1047.       hdr->unix_last_modified_stamp    =
  1048.     generic_to_unix_stamp (hdr->last_modified_stamp);
  1049.       break;
  1050.  
  1051.     default:
  1052.       generic_to_unix_filename (hdr->name, name_length);
  1053.       hdr->unix_last_modified_stamp    =
  1054.     generic_to_unix_stamp (hdr->last_modified_stamp);
  1055.     }
  1056.  
  1057.   return TRUE;
  1058. }
  1059.  
  1060. init_header (name, v_stat, hdr)
  1061.      char *name;
  1062.      struct stat *v_stat;
  1063.      LzHeader *hdr;
  1064. {
  1065.   bcopy (LZHUFF1_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  1066.   hdr->packed_size        = 0;
  1067.   hdr->original_size        = v_stat->st_size;
  1068.   hdr->last_modified_stamp      = unix_to_generic_stamp (v_stat->st_mtime);
  1069. #ifdef MSDOS
  1070.   getfilemode(name, &(hdr->attribute));
  1071. #else
  1072.   hdr->attribute                = GENERIC_ATTRIBUTE;
  1073. #endif
  1074.   strcpy (hdr->name, name);
  1075.   hdr->crc            = 0x0000;
  1076.   hdr->extend_type              = OUR_EXTEND;
  1077.   hdr->unix_last_modified_stamp    = v_stat->st_mtime;
  1078.                 /* 00:00:00 since JAN.1.1970 */
  1079. #ifdef NOT_COMPATIBLE_MODE
  1080.   hdr->unix_mode        = v_stat->st_mode;
  1081. #else
  1082.   hdr->unix_mode        = v_stat->st_mode;
  1083. #endif
  1084.  
  1085.   hdr->unix_uid            = v_stat->st_uid;
  1086.   hdr->unix_gid            = v_stat->st_gid;
  1087.  
  1088.   if ((v_stat->st_mode & S_IFMT) == S_IFDIR)
  1089.     {
  1090.       bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  1091.       hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
  1092.       hdr->original_size = 0;
  1093.       strcat (hdr->name, "/");
  1094.     }
  1095. }
  1096.  
  1097. /* Write only unix extended header. */
  1098. write_header (nafp, hdr)
  1099.      FILE *nafp;
  1100.      LzHeader *hdr;
  1101. {
  1102.   int        header_size;
  1103.   int        name_length;
  1104.   char          data[LZHEADER_STRAGE], *ptr;
  1105.   int           cnt;
  1106.  
  1107.   bzero (data, LZHEADER_STRAGE);
  1108.   bcopy (hdr->method, data + I_METHOD, METHOD_TYPE_STRAGE);
  1109.   setup_put (data + I_PACKED_SIZE);
  1110.   put_longword (hdr->packed_size);
  1111.   put_longword (hdr->original_size);
  1112.   put_longword (hdr->last_modified_stamp);
  1113.   put_word (hdr->attribute);
  1114.   
  1115. #ifdef STRICT
  1116.  
  1117.   if ( hdr->name[1] == ':' )
  1118.   {
  1119.     name_length = strlen(hdr->name + 2);
  1120.     put_byte (name_length);
  1121.     bcopy (hdr->name + 2, data + I_NAME, name_length);
  1122.   }
  1123.   else
  1124.   {
  1125.     name_length = strlen(hdr->name);
  1126.     put_byte (name_length);
  1127.     bcopy (hdr->name, data + I_NAME, name_length);
  1128.   }
  1129.   
  1130.   for ( ptr = data + I_NAME, cnt = 0; cnt < name_length; ptr++, cnt++ )
  1131.   {
  1132.     *ptr = islower(*ptr)? toupper(*ptr) : *ptr;
  1133.  
  1134.     if ( *ptr == '/' )
  1135.       *ptr = '\\';
  1136.   }
  1137. #else
  1138.   name_length = strlen (hdr->name);
  1139.   put_byte (name_length);
  1140.   bcopy (hdr->name, data + I_NAME, name_length);
  1141. #endif
  1142.   
  1143.   setup_put (data + I_NAME + name_length);
  1144.   put_word (hdr->crc);
  1145. #ifdef STRICT
  1146.   header_size = I_EXTEND_TYPE - 2 + name_length;
  1147. #else
  1148.   put_byte (OUR_EXTEND);
  1149.   put_byte (CURRENT_UNIX_MINOR_VERSION);
  1150.   put_longword ((long)hdr->unix_last_modified_stamp);
  1151.   put_word (hdr->unix_mode);
  1152.   put_word (hdr->unix_uid);
  1153.   put_word (hdr->unix_gid);
  1154.   header_size = I_UNIX_EXTEND_BOTTOM - 2 + name_length;
  1155. #endif
  1156.   data[I_HEADER_SIZE] = header_size;
  1157.   data[I_HEADER_CHECKSUM] = calc_sum (data + I_METHOD, header_size);
  1158.  
  1159.   if (fwrite (data, sizeof (char), header_size + 2, nafp) == NULL)
  1160.     error ("cannot write to temporary file");
  1161. }
  1162.  
  1163. boolean archive_is_msdos_sfx1 (name)
  1164.      char *name;
  1165. {
  1166.   int    len = strlen (name);
  1167.   return ((len >= 4) &&
  1168.       (strcmp (name + len - 4, ".com") == 0 ||
  1169.        strcmp (name + len - 4, ".exe") == 0));
  1170. }
  1171.  
  1172. boolean skip_msdos_sfx1_code (fp)
  1173.      FILE *fp;
  1174. {
  1175.   unsigned char buffer[2048];
  1176.   unsigned char *p, *q;
  1177.   int    n;
  1178.  
  1179.   n = fread (buffer, sizeof (char), 2048, fp);
  1180.  
  1181.   for (p = buffer + 2, q = buffer + n - 5; p < q; p ++)
  1182.     {
  1183.       /* found "-l??-" keyword (as METHOD type string) */
  1184.       if (p[0] == '-' && p[1] == 'l' && p[4] == '-')
  1185.     {
  1186.       /* size and checksum validate check */
  1187.       if (p[-2] > 20 && p[-1] == calc_sum (p, p[-2]))
  1188.         {
  1189.               fseek (fp, (long) ((p - 2) - buffer) - n, SEEK_CUR);
  1190.           return TRUE;
  1191.         }
  1192.     }
  1193.     }
  1194.  
  1195.   fseek (fp, (long) -n, SEEK_CUR);
  1196.   return FALSE;
  1197. }
  1198.  
  1199.  
  1200. /*----------------------------------------------------------------------*/
  1201. /*                                    */
  1202. /*----------------------------------------------------------------------*/
  1203.  
  1204. make_tmp_name (original, name)
  1205.      char *original;
  1206.      char *name;
  1207. {
  1208. #ifdef TMP_FILENAME_TEMPLATE
  1209.   /* "/tmp/lhXXXXXX" etc. */
  1210.   strcpy (name, TMP_FILENAME_TEMPLATE);
  1211. #else
  1212.   char *p, *s;
  1213.  
  1214.   strcpy (name, original);
  1215.   for (p = name, s = (char*)0; *p; p++)
  1216.     if (*p == '/' || *p == '\\')
  1217.       s = p;
  1218.  
  1219.   strcpy ((s ? s+1 : name), "lhXXXXXX");
  1220. #endif
  1221.  
  1222.   mktemp (name);
  1223. }
  1224.  
  1225. make_backup_name (name, orginal)
  1226.      char *name;
  1227.      char *orginal;
  1228. {
  1229.   register char *p, *dot;
  1230.  
  1231.   strcpy (name, orginal);
  1232.   for (p = name, dot = (char*)0; *p; p ++)
  1233.     {
  1234.       if (*p == '.')
  1235.     dot = p;
  1236.       else if (*p == '/' || *p == '\\')
  1237.     dot = (char*)0;
  1238.     }
  1239.  
  1240.   if (dot)
  1241.     p = dot;
  1242.  
  1243. #ifdef BACKUPNAME_EXTENTION
  1244.   strcpy (p, BACKUPNAME_EXTENTION)
  1245. #else
  1246.   strcpy (p, ".bak");
  1247. #endif
  1248. }
  1249.  
  1250. make_standard_archive_name (name, orginal)
  1251.      char *name;
  1252.      char *orginal;
  1253. {
  1254.   register char *p, *dot;
  1255.  
  1256.   strcpy (name, orginal);
  1257.   for (p = name, dot = (char*)0; *p; p ++)
  1258.     {
  1259.       if (*p == '.')
  1260.     dot = p;
  1261.       else if (*p == '/' || *p == '\\')
  1262.     dot = (char*)0;
  1263.     }
  1264.  
  1265.   if (dot)
  1266.     p = dot;
  1267.  
  1268. #ifdef ARCHIVENAME_EXTENTION
  1269.   strcpy (p, ARCHIVENAME_EXTENTION);
  1270. #else
  1271.   strcpy (p, ".lzh");
  1272. #endif
  1273. }
  1274.  
  1275. /*----------------------------------------------------------------------*/
  1276. /*                                    */
  1277. /*----------------------------------------------------------------------*/
  1278.  
  1279.  
  1280. boolean need_file (name)
  1281.      char *name;
  1282. {
  1283.   int    i;
  1284.  
  1285.   if (cmd_filec == 0)
  1286.     return TRUE;
  1287.  
  1288.   for (i = 0; i < cmd_filec; i ++)
  1289.     {
  1290.       if (STRING_COMPARE (cmd_filev[i], name) == 0)
  1291.     return TRUE;
  1292.     }
  1293.  
  1294.   return FALSE;
  1295. }
  1296.  
  1297. FILE *xfopen (name, mode)
  1298.      char *name, *mode;
  1299. {
  1300.   FILE *fp;
  1301.  
  1302.   if ((fp = fopen (name, mode)) == NULL)
  1303.     error (name);
  1304.  
  1305.   return fp;
  1306. }
  1307.  
  1308.  
  1309. /*----------------------------------------------------------------------*/
  1310. /*        Listing Stuff                        */
  1311. /*----------------------------------------------------------------------*/
  1312.  
  1313. /* need 14 or 22 (when long_format_listing is TRUE) column spaces */
  1314. print_size (packed_size, original_size)
  1315.      long packed_size, original_size;
  1316. {
  1317.   if (long_format_listing)
  1318.     printf ("%7ld ", packed_size);
  1319.  
  1320.   printf ("%7ld ", original_size);
  1321.  
  1322.   if (original_size == 0L)
  1323.     printf ("******");
  1324.   else
  1325.     printf ("%3d.%1d%%",
  1326.         (int)((packed_size * 100L) / original_size),
  1327.         (int)((packed_size * 1000L) / original_size) % 10);
  1328. }
  1329.  
  1330. /* need 12 or 17 (when long_format_listing is TRUE) column spaces */
  1331. print_stamp (t)
  1332.      time_t t;
  1333. {
  1334.   static boolean    got_now = FALSE;
  1335.   static time_t        now;
  1336.   static unsigned int    threshold;
  1337.   static char   t_month[12*3+1] = "JanFebMarAprMayJunJulAugSepOctNovDec";
  1338.   struct tm        *p;
  1339.  
  1340.   if (t == 0)
  1341.     {
  1342.       if (long_format_listing)
  1343.     printf ("                 "); /* 17 spaces */
  1344.       else
  1345.     printf ("            ");    /* 12 spaces */
  1346.  
  1347.       return;
  1348.     }
  1349.  
  1350.   if (!got_now)
  1351.     {
  1352.       time (&now);
  1353.       p = localtime (&now);
  1354.       threshold = p->tm_year * 12 + p->tm_mon - 6;
  1355.       got_now = TRUE;
  1356.     }
  1357.  
  1358.   p = localtime (&t);
  1359.  
  1360.   if (long_format_listing)
  1361.     printf ("%.3s %2d %02d:%02d %04d",
  1362.         &t_month[p->tm_mon * 3], p->tm_mday,
  1363.         p->tm_hour, p->tm_min, p->tm_year + 1900);
  1364.   else
  1365.     if (p->tm_year * 12 + p->tm_mon > threshold)
  1366.       printf ("%.3s %2d %02d:%02d",
  1367.           &t_month[p->tm_mon * 3], p->tm_mday, p->tm_hour, p->tm_min);
  1368.     else
  1369.       printf ("%.3s %2d  %04d",
  1370.           &t_month[p->tm_mon * 3], p->tm_mday, p->tm_year + 1900);
  1371. }
  1372.  
  1373. print_bar ()
  1374. {
  1375.   /* 17+1+(0 or 7+1)+7+1+6+1+(0 or 1+4)+(12 or 17)+1+20 */
  1376.   /*       12345678901234567_  1234567_123456  _123456789012   1234      */
  1377.   if (long_format_listing)
  1378. #ifdef STRICT
  1379.     printf ("------- ------- ------ ---- ----------------- -------------\n");
  1380. #else
  1381.     printf ("----------------- ------- ------- ------ ---- ----------------- -------------\n");
  1382. #endif
  1383.   else
  1384. #ifdef STRICT
  1385.     printf ("------- ------ ------------ --------------------\n");
  1386. #else
  1387.     printf ("----------------- ------- ------ ------------ --------------------\n");
  1388. #endif
  1389. }
  1390.  
  1391.  
  1392. /*
  1393.   view
  1394.  */
  1395. cmd_view ()
  1396. {
  1397.   FILE        *fp;
  1398.   LzHeader    hdr;
  1399.   register char    *p;
  1400.   long        a_packed_size = 0L;
  1401.   long        a_original_size = 0L;
  1402.   int        n_files = 0;
  1403.   struct stat    v_stat;
  1404.  
  1405.   if ((fp = fopen (archive_name, RMODE)) == NULL)
  1406.     if (!expand_archive_name (expanded_archive_name, archive_name))
  1407.       error (archive_name);
  1408.     else
  1409.       {
  1410.     errno = 0;
  1411.         fp = xfopen (expanded_archive_name, RMODE);
  1412.     archive_name = expanded_archive_name;
  1413.       }
  1414.  
  1415.   if (archive_is_msdos_sfx1 (archive_name))
  1416.     {
  1417.       skip_msdos_sfx1_code (fp);
  1418.     }
  1419.  
  1420.   if (!quiet)
  1421.     {
  1422.       /*       12345678901234567_  1234567_123456  _  123456789012  1234 */
  1423. #ifdef STRICT
  1424.       printf ("%s   SIZE  RATIO%s %s    STAMP   %s NAME\n",
  1425. #else
  1426.       printf (" PERMSSN  UID GID %s   SIZE  RATIO%s %s    STAMP   %s NAME\n",
  1427. #endif
  1428.           long_format_listing ? " PACKED " : "", /* 8,0 */
  1429.           long_format_listing ? "  CRC" : "", /* 5,0 */
  1430.           long_format_listing ? "  " : "", /* 2,0 */
  1431.           long_format_listing ? "   " : ""); /* 3,0 */
  1432.       print_bar ();
  1433.     }
  1434.  
  1435.   while (get_header (fp, &hdr))
  1436.     {
  1437.       if (need_file (hdr.name))
  1438.     {
  1439.       if (hdr.extend_type == EXTEND_UNIX)
  1440.             {
  1441. #ifndef STRICT
  1442.               printf ("%c%c%c%c%c%c%c%c%c%4d/%-4d",
  1443.           ((hdr.unix_mode & UNIX_OWNER_READ_PERM)  ? 'r' : '-'),
  1444.           ((hdr.unix_mode & UNIX_OWNER_WRITE_PERM) ? 'w' : '-'),
  1445.           ((hdr.unix_mode & UNIX_OWNER_EXEC_PERM)  ? 'x' : '-'),
  1446.           ((hdr.unix_mode & UNIX_GROUP_READ_PERM)  ? 'r' : '-'),
  1447.           ((hdr.unix_mode & UNIX_GROUP_WRITE_PERM) ? 'w' : '-'),
  1448.           ((hdr.unix_mode & UNIX_GROUP_EXEC_PERM)  ? 'x' : '-'),
  1449.           ((hdr.unix_mode & UNIX_OTHER_READ_PERM)  ? 'r' : '-'),
  1450.           ((hdr.unix_mode & UNIX_OTHER_WRITE_PERM) ? 'w' : '-'),
  1451.           ((hdr.unix_mode & UNIX_OTHER_EXEC_PERM)  ? 'x' : '-'),
  1452.           hdr.unix_uid, hdr.unix_gid);
  1453. #endif
  1454.         }
  1455.       else
  1456.         {
  1457.           switch (hdr.extend_type)
  1458.         {            /* max 18 characters */
  1459.                 case EXTEND_GENERIC:    p = "[Generic]"; break;
  1460.  
  1461.         case EXTEND_CPM:    p = "[CP/M]"; break;
  1462.  
  1463.           /* OS-9 and FLEX's CPU is MC-6809. I like it. :-)  */
  1464.         case EXTEND_FLEX:    p = "[FLEX]"; break;
  1465.  
  1466.         case EXTEND_OS9:    p = "[OS-9]"; break;
  1467.  
  1468.           /* I guessed from this ID.  Is this right? */
  1469.         case EXTEND_OS68K:    p = "[OS-9/68K]"; break;
  1470.  
  1471.         case EXTEND_MSDOS:    p = "[MS-DOS]"; break;
  1472.  
  1473.           /* I have Macintosh. :-)  */
  1474.         case EXTEND_MACOS:    p = "[Mac OS]"; break;
  1475.  
  1476.         case EXTEND_OS2:    p = "[OS/2]"; break;
  1477.  
  1478.         case EXTEND_HUMAN:    p = "[Human68K]"; break;
  1479.  
  1480.         case EXTEND_OS386:    p = "[OS-386]"; break;
  1481.  
  1482. #ifdef EXTEND_TOWNSOS
  1483.           /* This ID isn't fixed */
  1484.         case EXTEND_TOWNSOS:    p = "[TownsOS]"; break;
  1485. #endif
  1486.  
  1487.           /* Ouch!  Please customize it's ID.  */
  1488.                 default:                p = "[Unknown]"; break;
  1489.                 }
  1490. #ifndef STRICT
  1491.               printf ("%-18.18s", p);
  1492. #endif
  1493.         }
  1494.  
  1495.       print_size (hdr.packed_size, hdr.original_size);
  1496.  
  1497.       if (long_format_listing)
  1498.         if (hdr.has_crc)
  1499.           printf (" %04x", hdr.crc);
  1500.         else
  1501.           printf (" ****");
  1502.  
  1503.       printf (" ");
  1504.       print_stamp (hdr.unix_last_modified_stamp);
  1505.       printf (" %s\n", hdr.name);
  1506.       n_files ++;
  1507.       a_packed_size += hdr.packed_size;
  1508.       a_original_size += hdr.original_size;
  1509.     }
  1510.       fseek (fp, hdr.packed_size, SEEK_CUR);
  1511.     }
  1512.  
  1513.   fclose (fp);
  1514.   if (!quiet)
  1515.     {
  1516.       print_bar ();
  1517.  
  1518. #ifndef STRICT
  1519.       printf (" Total %4d file%c ",
  1520.           n_files, (n_files == 1) ? ' ' : 's');
  1521. #endif
  1522.       print_size (a_packed_size, a_original_size);
  1523.       printf (" ");
  1524.  
  1525.       if (long_format_listing)
  1526.     printf ("     ");
  1527.  
  1528.       if (stat (archive_name, &v_stat) < 0)
  1529.     print_stamp ((time_t)0);
  1530.       else
  1531.     print_stamp (v_stat.st_mtime);
  1532.  
  1533. #ifdef STRICT
  1534.       printf (" %4d file%c ",
  1535.           n_files, (n_files == 1) ? ' ' : 's');
  1536. #endif
  1537.       printf ("\n");
  1538.     }
  1539.  
  1540.   return;
  1541. }
  1542.  
  1543.  
  1544. boolean make_parent_path (name)
  1545.      char *name;
  1546. {
  1547.   char        path[FILENAME_LENGTH];
  1548.   struct stat    v_stat;
  1549.   register char    *p;
  1550.  
  1551.  /* make parent directory name into PATH for recursive call */
  1552.   strcpy (path, name);
  1553.   for (p = path + strlen (path); p > path; p --)
  1554.     if (p[-1] == '/' || p[-1] == '\\')
  1555.       {
  1556.     p[-1] = '\0';
  1557.     break;
  1558.       }
  1559.  
  1560.   if (p == path)
  1561.     return FALSE;        /* no more parent. */
  1562.  
  1563.   if (stat (path, &v_stat) >= 0)
  1564.     {
  1565.       if ((v_stat.st_mode & S_IFMT) != S_IFDIR)
  1566.     return FALSE;        /* already exist. but it isn't directory. */
  1567.       return TRUE;        /* already exist its directory. */
  1568.     }
  1569.  
  1570.   errno = 0;
  1571.  
  1572.   if (!quiet)
  1573.     message ("Making Directory", path);
  1574.  
  1575.   if (mkdir (path, 0777) >= 0)    /* try */
  1576.     return TRUE;        /* successful done. */
  1577.  
  1578.   errno = 0;
  1579.  
  1580.   if (!make_parent_path (path))
  1581.     return FALSE;
  1582.  
  1583.   if (mkdir (path, 0777) < 0)        /* try again */
  1584.     return FALSE;
  1585.  
  1586.   return TRUE;
  1587. }
  1588.  
  1589. FILE *open_with_make_path (name)
  1590.      char *name;
  1591. {
  1592.   FILE        *fp;
  1593.   struct stat    v_stat;
  1594.   char        buffer[1024];
  1595.  
  1596.   if (stat (name, &v_stat) >= 0)
  1597.     {
  1598.       if ((v_stat.st_mode & S_IFMT) != S_IFREG)
  1599.     return NULL;
  1600.  
  1601.       if (!force)
  1602.     {
  1603.       for (;;)
  1604.         {
  1605.           fprintf (stderr, "%s OverWrite ?(Yes/No/All) ", name);
  1606.           fflush (stderr);
  1607.           gets (buffer);
  1608.           if (buffer[0] == 'N' || buffer[0] == 'n')
  1609.         return NULL;
  1610.           if (buffer[0] == 'Y' || buffer[0] == 'y')
  1611.         break;
  1612.           if (buffer[0] == 'A' || buffer[0] == 'a')
  1613.         {
  1614.           force = TRUE;
  1615.           break;
  1616.         }
  1617.         }
  1618.     }
  1619.     }
  1620.  
  1621.   fp = fopen (name, WMODE);
  1622.   if (!fp)
  1623.     {
  1624.       errno = 0;
  1625.       if (!make_parent_path (name))
  1626.     return NULL;
  1627.  
  1628.       fp = fopen (name, WMODE);
  1629.       if (!fp)
  1630.         message ("Error:", name);
  1631.     }
  1632.   return fp;
  1633. }
  1634.  
  1635. #ifdef MSDOS
  1636. void dosname(char *name)
  1637. {
  1638.   char *ptr, *first = NULL, *last = NULL;
  1639.   char temp[8];
  1640.  
  1641.   for ( ptr = strchr(name, 0); ptr >= name; ptr-- )
  1642.     if ( *ptr == '.' )
  1643.     {
  1644.       if ( last == NULL )
  1645.         last = ptr;
  1646.     }
  1647.     else if ( (*ptr == '/') || (*ptr == '\\') )
  1648.     {
  1649.       first = ptr + 1;
  1650.       break;
  1651.     }
  1652.  
  1653.   if ( first == NULL )
  1654.     first = name;
  1655.   if ( last == NULL )
  1656.     last = strchr(name, 0);
  1657.  
  1658.   for ( ptr = first; ptr < last; ptr++ )
  1659.     if ( *ptr == '.' )
  1660.       *ptr = '_';
  1661.  
  1662.   if ( strlen(last) > 4 )
  1663.     last[4] = 0;
  1664.  
  1665.   if ( last - first > 8 )
  1666.   {
  1667.     strcpy(temp, last);
  1668.     strcpy(first + 8, last);
  1669.   }
  1670. }
  1671. #endif
  1672.  
  1673. extern int decode_lzhuf (), decode_larc ();
  1674. extern int decode_stored_crc (), decode_stored_nocrc ();
  1675.  
  1676. extract_one (fp, hdr)
  1677.      FILE *fp;
  1678.      LzHeader *hdr;
  1679. {
  1680.   FILE        *ofp;        /* output file */
  1681.   char        name[1024];
  1682.   time_t    utimebuf[2];
  1683.   int        crc;
  1684.   int        (*decode_proc)(); /* (ifp,ofp,original_size,name) */
  1685.   int        save_quiet;
  1686.  
  1687.   strcpy (name, hdr->name);
  1688.   if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
  1689.     {
  1690.       if (bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) == 0)
  1691.     decode_proc = decode_lzhuf;
  1692.       else if ((bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) == 0) ||
  1693.            (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) == 0))
  1694.     decode_proc = (hdr->has_crc) ? decode_stored_crc : decode_stored_nocrc;
  1695.       else if (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) == 0)
  1696.     decode_proc = decode_larc;
  1697.       else
  1698.         message ("Error:", "Sorry, Cannot Extract this method.");
  1699.  
  1700.       reading_filename = archive_name;
  1701.       writting_filename = name;
  1702.       if (output_to_stdout)
  1703.     {
  1704.           if (!quiet)
  1705.             printf ("::::::::\r\n%s\r\n::::::::\r\n", name);
  1706.  
  1707.           if ( strlen(pager) != 0 )
  1708.             ofp = popen(pager, WMODE);
  1709.           else
  1710.             ofp = stdout;
  1711.  
  1712.       save_quiet = quiet;
  1713.           quiet = TRUE;
  1714.           crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
  1715.           quiet = save_quiet;
  1716.  
  1717.           if ( strlen(pager) != 0 )
  1718.             pclose(ofp);
  1719.     }
  1720.       else if (output_to_test)
  1721.         {
  1722.           ofp = fopen(NULLFILE, WMODE);
  1723.           crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
  1724.           fclose(ofp);
  1725.         }
  1726.       else
  1727.         {
  1728. #ifdef MSDOS
  1729.           dosname(name);
  1730. #endif
  1731.       if ((ofp = open_with_make_path (name)) == NULL)
  1732.         return;
  1733.       else
  1734.         {
  1735.           crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
  1736.           fclose (ofp);
  1737.         }
  1738.     }
  1739.  
  1740.       if (hdr->has_crc && (crc != hdr->crc))
  1741.         if (output_to_test)
  1742.           message ("Error:", "CRC failed\a");
  1743.         else
  1744.           error ("CRC failed\a");
  1745.     }
  1746.   else
  1747.     {
  1748.       /* NAME has trailing SLASH '/', (^_^) */
  1749.       if (!output_to_stdout &&
  1750.       !make_parent_path (name))
  1751.     error (name);
  1752.     }
  1753.  
  1754.   if (!output_to_stdout && !output_to_test)
  1755.     {
  1756.       utimebuf[0] = utimebuf[1] = hdr->unix_last_modified_stamp;
  1757.       utime (name, utimebuf);
  1758.  
  1759. #ifdef NOT_COMPATIBLE_MODE
  1760.       setfilemode(name, hdr->attribute);
  1761. #else
  1762.       chmod (name, hdr->unix_mode);
  1763. #endif
  1764.  
  1765. #ifndef MSDOS
  1766.       chown (name, hdr->unix_uid, hdr->unix_gid);
  1767. #endif
  1768.       errno = 0;
  1769.     }
  1770. }
  1771.  
  1772.  
  1773. /*
  1774.   extract
  1775.  */
  1776. cmd_extract ()
  1777. {
  1778.   LzHeader    hdr;
  1779.   long        pos;
  1780.   FILE        *fp;
  1781.  
  1782.   if ((fp = fopen (archive_name, RMODE)) == NULL)
  1783.     if (!expand_archive_name (expanded_archive_name, archive_name))
  1784.       error (archive_name);
  1785.     else
  1786.       {
  1787.     errno = 0;
  1788.         fp = xfopen (expanded_archive_name, RMODE);
  1789.     archive_name = expanded_archive_name;
  1790.       }
  1791.  
  1792.   if (archive_is_msdos_sfx1 (archive_name))
  1793.     {
  1794.       skip_msdos_sfx1_code (fp);
  1795.     }
  1796.  
  1797.   while (get_header (fp, &hdr))
  1798.     {
  1799.       if (need_file (hdr.name))
  1800.     {
  1801.       pos = ftell (fp);
  1802.       extract_one (fp, &hdr);
  1803.       fseek (fp, pos + hdr.packed_size, SEEK_SET);
  1804.     } else {
  1805.       fseek (fp, hdr.packed_size, SEEK_CUR);
  1806.     }
  1807.     }
  1808.  
  1809.   fclose (fp);
  1810.  
  1811.   return;
  1812. }
  1813.  
  1814. /*----------------------------------------------------------------------*/
  1815. /*                                    */
  1816. /*----------------------------------------------------------------------*/
  1817.  
  1818. extern int encode_lzhuf ();
  1819. extern int encode_storerd_crc ();
  1820.  
  1821. append_one (fp, nafp, hdr)
  1822.      FILE *fp, *nafp;
  1823.      LzHeader *hdr;
  1824. {
  1825.   long    header_pos, next_pos, org_pos, data_pos;
  1826.   long    v_original_size, v_packed_size;
  1827.  
  1828.   reading_filename = hdr->name;
  1829.   writting_filename = temporary_name;
  1830.  
  1831.   org_pos = ftell (fp);
  1832.   header_pos = ftell (nafp);
  1833.   write_header (nafp, hdr);    /* DUMMY */
  1834.  
  1835.   if (hdr->original_size == 0){
  1836.         printf("%s - not frozen\n",hdr->name);
  1837.         return;         /* previous write_header is not DUMMY. (^_^) */
  1838.   }
  1839.  
  1840.   data_pos = ftell (nafp);
  1841.   hdr->crc = encode_lzhuf (fp, nafp, hdr->original_size,
  1842.                &v_original_size, &v_packed_size, hdr->name);
  1843.   if (v_packed_size < v_original_size)
  1844.     {
  1845.       next_pos = ftell (nafp);
  1846.     }
  1847.   else
  1848.     {                /* retry by stored method */
  1849.       fseek (fp, org_pos, SEEK_SET);
  1850.       fseek (nafp, data_pos, SEEK_SET);
  1851.       hdr->crc = encode_stored_crc (fp, nafp, hdr->original_size,
  1852.                     &v_original_size, &v_packed_size);
  1853.       fflush (nafp);
  1854.       next_pos = ftell (nafp);
  1855.       ftruncate (fileno (nafp), next_pos);
  1856.       bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  1857.     }
  1858.   hdr->original_size = v_original_size;
  1859.   hdr->packed_size = v_packed_size;
  1860.   fseek (nafp, header_pos, SEEK_SET);
  1861.   write_header (nafp, hdr);
  1862.   fseek (nafp, next_pos, SEEK_SET);
  1863. }
  1864.  
  1865. write_tail (nafp)
  1866.      FILE *nafp;
  1867. {
  1868.   putc (0x00, nafp);
  1869. }
  1870.  
  1871. copy_old_one (oafp, nafp, hdr)
  1872.      FILE *oafp, *nafp;
  1873.      LzHeader *hdr;
  1874. {
  1875.   if (noexec)
  1876.     {
  1877.       fseek (oafp, (long)(hdr->header_size + 2) + hdr->packed_size, SEEK_CUR);
  1878.     }
  1879.   else
  1880.     {
  1881.       reading_filename = archive_name;
  1882.       writting_filename = temporary_name;
  1883.       copy_file (oafp, nafp, (long)(hdr->header_size + 2) + hdr->packed_size);
  1884.     }
  1885. }
  1886.  
  1887.  
  1888. FILE *append_it (name, oafp, nafp)
  1889.      char *name;
  1890.      FILE *oafp, *nafp;
  1891. {
  1892.   LzHeader    ahdr, hdr;
  1893.   FILE        *fp;
  1894.   long        old_header;
  1895.   int        cmp;
  1896.   int        filec;
  1897.   char        **filev;
  1898.   int        i;
  1899.  
  1900.   struct stat    v_stat;
  1901.   boolean    directory;
  1902.  
  1903.   if (!delete_from_archive)
  1904.     if (stat (name, &v_stat) < 0)
  1905.       {
  1906.         message ("Error:", name);
  1907.         return oafp;
  1908.       }
  1909.  
  1910.   directory = ((v_stat.st_mode & S_IFMT) == S_IFDIR);
  1911.  
  1912.   init_header (name, &v_stat, &hdr);
  1913.  
  1914.   if (!delete_from_archive && !directory && !noexec)
  1915.     fp = xfopen (name, RMODE);
  1916.  
  1917.   while (oafp)
  1918.     {
  1919.       old_header = ftell (oafp);
  1920.       if (!get_header (oafp, &ahdr))
  1921.     {
  1922.       fclose (oafp);
  1923.       oafp = NULL;
  1924.       break;
  1925.     }
  1926.       else
  1927.     {
  1928.       cmp = STRING_COMPARE (ahdr.name, hdr.name);
  1929.       if (cmp < 0)
  1930.         {        /* SKIP */
  1931.           fseek (oafp, old_header, SEEK_SET);
  1932.           copy_old_one (oafp, nafp, &ahdr);
  1933.         }
  1934.       else if (cmp == 0)
  1935.         {        /* REPLACE */
  1936.           fseek (oafp, ahdr.packed_size, SEEK_CUR);
  1937.           break;
  1938.         }
  1939.       else        /* cmp > 0, INSERT */
  1940.         {
  1941.           fseek (oafp, old_header, SEEK_SET);
  1942.           break;
  1943.         }
  1944.     }
  1945.     }
  1946.  
  1947.   if (delete_from_archive)
  1948.     {
  1949.       if (noexec)
  1950.         fprintf (stderr, "DELETE %s\n", name);
  1951.       else
  1952.         printf ("%s - Deleted\n", name);
  1953.     }
  1954.   else
  1955.     {
  1956.       if ( !oafp || (cmp > 0) || !update_if_newer
  1957.            || (ahdr.unix_last_modified_stamp < hdr.unix_last_modified_stamp) )
  1958.     {
  1959.       if (noexec)
  1960.         fprintf (stderr, "APPEND %s\n", name);
  1961.           else
  1962. #ifdef STRICT
  1963.             if ( !directory )
  1964. #endif
  1965.               if ( !update_freshen || (cmp == 0) )
  1966.                 append_one (fp, nafp, &hdr);
  1967.     }
  1968.       else
  1969.     {                    /* archive has old one */
  1970.       fseek (oafp, old_header, SEEK_SET);
  1971.       copy_old_one (oafp, nafp, &ahdr);
  1972.     }
  1973.  
  1974.       if (!directory)
  1975.     {
  1976.       if (!noexec)
  1977.         fclose (fp);
  1978.     }
  1979.       else
  1980.     {            /* recurcive call */
  1981.       if (find_files (name, &filec, &filev))
  1982.         {
  1983.           for (i = 0; i < filec; i ++)
  1984.         oafp = append_it (filev[i], oafp, nafp);
  1985.           free_files (filec, filev);
  1986.         }
  1987.       return oafp;
  1988.     }
  1989.     }
  1990.  
  1991.   return oafp;
  1992. }
  1993.  
  1994.  
  1995. remove_it (name)
  1996.      char *name;
  1997. {
  1998.   struct stat    v_stat;
  1999.   int        i;
  2000.   char        **filev;
  2001.   int        filec;
  2002.  
  2003.   if (stat (name, &v_stat) < 0)
  2004.     {
  2005.       fprintf (stderr, "Cannot access \"%s\".\n", name);
  2006.       return;
  2007.     }
  2008.  
  2009.   if ((v_stat.st_mode & S_IFMT) == S_IFDIR)
  2010.     {
  2011.       if (!find_files (name, &filec, &filev))
  2012.     {
  2013.           fprintf (stderr, "Cannot open directory \"%s\".\n", name);
  2014.       return;
  2015.     }
  2016.  
  2017.       for (i = 0; i < filec; i ++)
  2018.     remove_it (filev[i]);
  2019.  
  2020.       free_files (filec, filev);
  2021.  
  2022.       if (noexec)
  2023.         printf ("REMOVE DIR %s\n", name);
  2024.       else if (rmdir (name) < 0)
  2025.         fprintf (stderr, "Cannot remove directory \"%s\".\n", name);
  2026.       else if (!quiet)
  2027.         printf ("%s - Removed\n", name);
  2028.     }
  2029.   else
  2030.     {
  2031.       if (noexec)
  2032.         printf ("REMOVE %s\n", name);
  2033.       else if (unlink (name) < 0)
  2034.         fprintf (stderr, "Cannot delete \"%s\".\n", name);
  2035.       else if (!quiet)
  2036.         printf ("%s - Removed\n", name);
  2037.     }
  2038. }
  2039.  
  2040. #ifdef FASTCOPY
  2041. #define BUFFER_SIZE 16384
  2042.  
  2043. #ifndef O_BINARY
  2044. #define O_BINARY 0
  2045. #endif
  2046.  
  2047. copy_archive(char *src, char *dst)
  2048. {
  2049.   int ih, oh;
  2050.   unsigned chunk;
  2051.   char *buffer = (char *) rson;
  2052.  
  2053.   printf ("Copying temp to archive ... ");
  2054.  
  2055.   ih = open (src, O_RDONLY | O_BINARY);
  2056.   if ( ih == -1 )
  2057.     error(src);
  2058.   oh = open (dst, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
  2059.   if ( oh == -1 )
  2060.     error(dst);
  2061.  
  2062.   while ( (chunk = read(ih, buffer, BUFFER_SIZE)) > 0 )
  2063.     if ( write(oh, buffer, chunk) != chunk )
  2064.       error(dst);
  2065.  
  2066.   close (ih);
  2067.   close (oh);
  2068.  
  2069.   printf("\b\b\b\b   \b\b\b\b.\n");
  2070. }
  2071. #endif
  2072.  
  2073. cmd_append ()
  2074. {
  2075.   LzHeader    ahdr;
  2076.   FILE        *oafp, *nafp;
  2077.   char        backup_archive_name [ FILENAME_LENGTH ];
  2078.   char        new_archive_name_buffer [ FILENAME_LENGTH ];
  2079.   char        *new_archive_name;
  2080.   int        i;
  2081.   long        old_header;
  2082.   struct stat    v_stat;
  2083.   boolean    old_archive_exist;
  2084.  
  2085.   if (cmd_filec == 0)
  2086.     return;
  2087.  
  2088.   make_tmp_name (archive_name, temporary_name);
  2089.  
  2090.   if ((oafp = fopen (archive_name, RMODE)) == NULL)
  2091.     if (expand_archive_name (expanded_archive_name, archive_name))
  2092.       {
  2093.     errno = 0;
  2094.         oafp = fopen (expanded_archive_name, RMODE);
  2095.     archive_name = expanded_archive_name;
  2096.       }
  2097.  
  2098.   old_archive_exist = (oafp) ? TRUE : FALSE;
  2099.   if (new_archive && oafp)
  2100.     {
  2101.       fclose (oafp);
  2102.       oafp = NULL;
  2103.     }
  2104.  
  2105.   if (oafp && archive_is_msdos_sfx1 (archive_name))
  2106.     {
  2107.       skip_msdos_sfx1_code (oafp);
  2108.       make_standard_archive_name (new_archive_name_buffer, archive_name);
  2109.       new_archive_name = new_archive_name_buffer;
  2110.     }
  2111.   else
  2112.     {
  2113.       new_archive_name = archive_name;
  2114.     }
  2115.  
  2116.   errno = 0;
  2117.   if (!noexec)
  2118.     {
  2119.       nafp = xfopen (temporary_name, WMODE);
  2120.       remove_temporary_at_error = TRUE;
  2121.     }
  2122.  
  2123.   for (i = 0; i < cmd_filec; i ++)
  2124.     oafp = append_it (cmd_filev[i], oafp, nafp);
  2125.  
  2126.   if (oafp)
  2127.     {
  2128.       old_header = ftell (oafp);
  2129.       while (get_header (oafp, &ahdr))
  2130.     {
  2131.       fseek (oafp, old_header, SEEK_SET);
  2132.       copy_old_one (oafp, nafp, &ahdr);
  2133.       old_header = ftell (oafp);
  2134.     }
  2135.       fclose (oafp);
  2136.     }
  2137.  
  2138.   if (!noexec)
  2139.     {
  2140.       write_tail (nafp);
  2141.       fclose (nafp);
  2142.     }
  2143.  
  2144.   make_backup_name (backup_archive_name, archive_name);
  2145.  
  2146.   if (!noexec && old_archive_exist)
  2147.   {
  2148.     unlink(backup_archive_name);
  2149.  
  2150.     if (rename (archive_name, backup_archive_name) < 0)
  2151.       error (archive_name);
  2152.   }
  2153.  
  2154.   if (!quiet && new_archive_name == new_archive_name_buffer)
  2155.     {                /* warning at old archive is SFX */
  2156.       printf ("New Archive File is \"%s\"\n", new_archive_name);
  2157.     }
  2158.  
  2159.   if (!noexec && rename (temporary_name, new_archive_name) < 0)
  2160.     {
  2161.       if (stat (temporary_name, &v_stat) < 0)
  2162.     error (temporary_name);
  2163.  
  2164. #ifdef FASTCOPY
  2165.       copy_archive(temporary_name, archive_name);
  2166. #else
  2167.       oafp = xfopen (temporary_name, RMODE);
  2168.       nafp = xfopen (archive_name, WMODE);
  2169.       reading_filename = temporary_name;
  2170.       writting_filename = archive_name;
  2171.       copy_file (oafp, nafp, (long)v_stat.st_size);
  2172.       fclose (nafp);
  2173.       fclose (oafp);
  2174. #endif
  2175.  
  2176.       unlink (temporary_name);
  2177.     }
  2178.   remove_temporary_at_error = FALSE;
  2179.  
  2180.   if (delete_after_append)
  2181.     {
  2182.       if (!quiet && !noexec)
  2183.     printf ("Erasing...\n");
  2184.       for (i = 0; i < cmd_filec; i ++)
  2185.     remove_it (cmd_filev[i]);
  2186.     }
  2187.  
  2188.   return;
  2189. }
  2190.